<?php


namespace app\privatearea\controller;


use app\common\cachemodel\privatearea\PrivateAreaUser;
use app\common\lib\exception\ApiException;
use app\common\model\User;
use think\Controller;

class Auth extends Controller
{
    protected $headers = null;
    protected $user = null;
    protected $privateAreaUserInfo = null;
    protected $errermsg = '';
    protected $is_simulated = false;
    protected $avoidLoginAction = []; // 免登录 方法
    protected $isAdmin = false;

    public function _initialize()
    {
        parent::_initialize();

        $this->headers = $this->request->header();

        $action = $this->request->action(); // 全小写

        if (isset($this->headers['app-type']) && $this->headers['app-type'] === 'manage')
        {
            $this->isAdmin = true;
        }

        if (!$this->isLogin() && !in_array($action, $this->avoidLoginAction, true))
        {
            throw new ApiException($this->errermsg, 200, config('code.denied'));
        }
    }

    public function isLogin()
    {
        if (!isset($this->headers['access-token']) || empty($this->headers['access-token']))
        {
            $this->errermsg = '您的账户登录过期，请重新登录。';
            return false;
        }
        // access-token AES解密
        $accessUserToken = $this->decryptWithOpenssl($this->headers['access-token']);

        if (empty($accessUserToken)) throw new ApiException('前往登录', 200, 405);

        if (!preg_match('/||/', $accessUserToken))
        {
            $this->errermsg = '您的账户登录过期，请重新登录。';
            return false;
        }

        [$token, $privateAreaId] = explode('||', $accessUserToken);

        $privateAreaUserInfo = (new PrivateAreaUser())->getPrivateAreaInfo($privateAreaId);

        if (!$privateAreaUserInfo || $privateAreaUserInfo['token'] !== $token || $this->request->time() > $privateAreaUserInfo['token_expire'])
        {   // 判断token是否过期 并且账户状态正常
            throw new ApiException('登录失效', 200, config('code.denied'));
        }

        $this->privateAreaUserInfo = $privateAreaUserInfo;

        $id = (int)($privateAreaUserInfo['uid']);
        // 账号模拟
        $simulation = config('app.simulation');

        if ($id !== $simulation['from'])
        {
            $map['id'] = $id;
        } else
        {
            $map['id'] = $simulation['to'] ?: $id;
            if ($map['id'] === $simulation['to'])
            {   // 模拟登陆
                $this->is_simulated = true;
            }
        }

        $userinfo = (new User())->getUserinfo($map);

        $this->user = $userinfo;

        if (!$userinfo || empty($userinfo) || $userinfo['forbidden'] == 1) return false;

        /**
         * 定义全局常量 UID 方便日志打印带上用户ID信息
         */
        if (!defined('USERINFO_UID'))
        {
            define('USERINFO_UID', $userinfo['id']);
        }

        return true;
    }

    /**
     * 加密字符串
     * @param string $data 字符串
     * @return string
     */
    protected function encryptWithOpenssl($data): string
    {
        try
        {
            $config = config('privatearea');
            return base64_encode(openssl_encrypt($data, $config['aes_method'], $config['aes_key'], OPENSSL_RAW_DATA, $config['aes_iv']));
        }
        catch (\Exception $e)
        {
            return '';
        }

    }

    /**
     * 解密字符串
     * @param string $data 字符串
     * @return string
     */
    protected function decryptWithOpenssl($data): string
    {
        try
        {
            $config = config('privatearea');
            return openssl_decrypt(base64_decode($data), $config['aes_method'], $config['aes_key'], OPENSSL_RAW_DATA, $config['aes_iv']);
        }
        catch (\Exception $e)
        {
            return '';
        }
    }

    /**
     * 判断是否是微信浏览器
     */
    protected function isWexinBrowser(): bool
    {
        $userAgent = $this->request->header('user-agent');

        return strpos(strtolower($userAgent), 'micromessenger', 0);
    }


    /**
     * 通过code获取用户access_token和openid
     * @param array $wechatConfig
     * @param string $code
     * @return mixed|null
     */
    protected function wechatGetAccessTokenAndOpenidByCode(array $wechatConfig, string $code = '')
    {
        $resultData = null;
        try
        {
            $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$wechatConfig['appid']}&secret={$wechatConfig['secret']}&code={$code}&grant_type=authorization_code";

            if ($access_token_url)
            {
                $result = file_get_contents($access_token_url);

                //成功返回
                //{
                //     "access_token":"35_bIa5hTQdh2Eu8AVOw8zIalg_wudCdCErXJtRGqbhuVTk-mzca0Vzha_iQhZ-Sl1xlP6fu9PnkQz5beGb13-6ng",
                //     "expires_in":7200,
                //     "refresh_token":"35_4sd8r10q4JHyrE6R9oAY6GWUqIr52WcCQQNA88MwkSwVmb4F9cMbC1JM0ouOAVOU83NPtDhn-Q2oWdnGchyi-A",
                //     "openid":"oD2a60S82Ue72eKEQw97f7HCiHfY",
                //     "scope":"snsapi_base"
                // }
                $resultData = json_decode($result, true);
            }
        }
        catch (\Exception $e)
        {
            Log::write('获取 access_token 异常，信息为：' . $e->getMessage() . PHP_EOL, 'error', true);
        }

        return $resultData;
    }
}
